import os
from common.benchmark_var import GlobalEnv
from utils.executor import Executor
from workload.workloads_manager import WorkloadManager
from framework.native_workload import NativeWorkload
from common.benchmark_var import MeasureUnit
from framework.java_workload import JavaWorkload
from copy import deepcopy
import shutil

class VulkanWorkload(JavaWorkload):
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = ''
        self.lang = 'C'
        self.description = ''
        self.result_file_name = ''
        self.desc = ''
        self.TMPDIR = os.path.join(self.run_dir, 'tmp')
        self.program_options = ""
        self.support_multi_instance = False
        self.exe = ""
        self.script = "vulkan.sh"
        self.pathflag = 0
        self.valid = True

    def setup(self):
        self._copy_src2build()
        executor = Executor(desc='make_vulkan',
                        command='make -j',
                        exec_dir=self.build_dir,
                        debug=self.debug)
        res = executor.exec()

    def _copy_src2build(self):
        files = os.listdir(self.src_dir)
        for file in files:
            src_file = os.path.join(self.src_dir, file)
            dst_file = os.path.join(self.build_dir, file)
            if os.path.exists(dst_file):
                shutil.rmtree(dst_file) if os.path.isdir(dst_file) else os.remove(dst_file)
            if os.path.isdir(src_file):
                shutil.copytree(src_file, dst_file)
            else:
                shutil.copy(src_file, self.build_dir)

    def get_instance_cmd(self, instance):
        executors = []
        program = os.path.join(self.build_dir, self.script)
        cmd = "bash {} {}".format(program, self.program_options)
        executor = Executor(desc=self.desc,
                            command=cmd,
                            debug=self.debug,
                            exec_dir=instance.instance_dir)
        executors.append(executor)
        return executors

    def get_raw_score(self, instance):
        result_file = os.path.join(instance.instance_dir, self.result_file_name)
        if not os.path.exists(result_file):
            return 0
        with open(result_file, 'r') as f:
            lines = f.readlines()
            for i in range(len(lines)):
                score_line = lines[i].strip()
                if score_line.find('|') != -1:
                    str_list = score_line.split('|')
                    score = float(str_list[1])
                    return score
            return 0
        return 0


    def setup_dir(self):
        self.work_dir = os.path.join(GlobalEnv.GCBS_WORKLOAD_DIR, "vulkan")
        self.src_dir = os.path.join(self.work_dir, 'src')
        self.build_dir = os.path.join(self.work_dir, 'build')
        self.data_dir = os.path.join(self.work_dir, 'data')
        self.log_dir = os.path.join(self.work_dir, 'log')
        self.bin_dir = os.path.join(self.work_dir, 'bin')
        self.run_dir = os.path.join(self.work_dir, 'run', self.name)
        dir_list = [self.work_dir, self.src_dir, self.build_dir, self.data_dir,
                    self.log_dir, self.run_dir, self.bin_dir]
        for directory in dir_list:
            if not os.path.exists(directory):
                os.makedirs(directory)

@WorkloadManager.register_workload('vk_instance')
class VkInstanceWorkload(VulkanWorkload):
    DESC = "Vulkan: instance"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "vk_instance"
        self.description = VkInstanceWorkload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.result_file_name = "vk_instance.log"
        self.program_options = "-b instance"
        self.setup_dir()
        self.desc = "vk_instance"

@WorkloadManager.register_workload('vk_mesh')
class VkMeshWorkload(VulkanWorkload):
    DESC = "Vulkan: mesh"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "vk_mesh"
        self.description = VkMeshWorkload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.result_file_name = "vk_mesh.log"
        self.program_options = "-b mesh"
        self.setup_dir()
        self.desc = "vk_mesh"

@WorkloadManager.register_workload('vk_geom')
class VkGeomWorkload(VulkanWorkload):
    DESC = "Vulkan: geom"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "vk_geom"
        self.description = VkGeomWorkload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.result_file_name = "vk_geom.log"
        self.program_options = "-b meshgeom"
        self.setup_dir()
        self.desc = "vk_geom"


@WorkloadManager.register_workload('vk_tess')
class VkTessWorkload(VulkanWorkload):
    DESC = "Vulkan: tess"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "vk_tess"
        self.description = VkTessWorkload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.result_file_name = "vk_tess.log"
        self.program_options = "-b meshtess"
        self.setup_dir()
        self.desc = "vk_tess"

@WorkloadManager.register_workload('vk_model')
class VkModelWorkload(VulkanWorkload):
    DESC = "Vulkan: model"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "vk_model"
        self.description = VkModelWorkload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.result_file_name = "vk_model.log"
        self.program_options = "-b modelmodel"
        self.setup_dir()
        self.desc = "vk_model"

@WorkloadManager.register_workload('vk_buffer')
class VkBufferWorkload(VulkanWorkload):
    DESC = "Vulkan: buffer"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "vk_buffer"
        self.description = VkBufferWorkload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.result_file_name = "vk_buffer.log"
        self.program_options = "-b secondarycommandbuffer"
        self.setup_dir()
        self.desc = "vk_buffer"

@WorkloadManager.register_workload('vk_cube')
class VkCubeWorkload(VulkanWorkload):
    DESC = "Vulkan: cube"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "vk_cube"
        self.description = VkCubeWorkload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.result_file_name = "vk_cube.log"
        self.program_options = "-b cube"
        self.setup_dir()
        self.desc = "vk_cube"

@WorkloadManager.register_workload('vk_uniform')
class VkUniformWorkload(VulkanWorkload):
    DESC = "Vulkan: uniform"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "vk_uniform"
        self.description = VkUniformWorkload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.result_file_name = "vk_uniform.log"
        self.program_options = "-b dynamicuniform"
        self.setup_dir()
        self.desc = "vk_uniform"

@WorkloadManager.register_workload('vk_cartoon')
class VkCartoonWorkload(VulkanWorkload):
    DESC = "Vulkan: cartoon"
    def __init__(self, name, options, baseline):
        super().__init__(name, options, baseline)
        self.name = "vk_cartoon"
        self.description = VkCartoonWorkload.DESC
        self.unit_of_measure = MeasureUnit.SCORE
        self.result_file_name = "vk_cartoon.log"
        self.program_options = "-b cartoon"
        self.setup_dir()
        self.desc = "vk_cartoon"



